/*-----------------------------------------------------------------------*/
/* Low level disk I/O module skeleton for FatFs     (C)ChaN, 2007        */
/*-----------------------------------------------------------------------*/
/* This is a stub disk I/O module that acts as front end of the existing */
/* disk I/O modules and attach it to FatFs module with common interface. */
/*-----------------------------------------------------------------------*/
#include "includes.h"
#include "diskio.h"
#include "sdconfig.h"

/*-----------------------------------------------------------------------*/
/* Correspondence between physical drive number and physical drive.      */
/*-----------------------------------------------------------------------*/

#define ATA		1
#define MMC		0
#define USB		2

uint32 blk_start_addr=0xffffffee;

sd_struct hsmmc_card_0;


/*-----------------------------------------------------------------------*/
/* Inidialize a Drive                                                    */
/*-----------------------------------------------------------------------*/

DSTATUS disk_initialize (
	BYTE drv				/* Physical drive nmuber (0..) */
)
{
	DSTATUS stat=RES_OK;
	uint8 * init_buf;
	uint32 loop;
	switch (drv) {
	case ATA :
		//result = ATA_disk_initialize();
		// translate the reslut code here

		return stat;

	case MMC :
		init_buf = (uint8 *)&hsmmc_card_0;
		for(loop=0;loop<sizeof(sd_struct);loop++){
			*init_buf++ = 0;	
		}
		if(SD_Initialize(&hsmmc_card_0)==SD_NO_ERR){
	        //CopyMovitoMem(HSMMC_CHANNEL, 0,2, (uint *)FATFS_BUFFER_ADDR, MOVI_INIT_REQUIRED);
			SD_DisplayInfo(&hsmmc_card_0);
			SD_ReadBlock(&hsmmc_card_0,0,(uint8 *)FATFS_BUFFER_ADDR);
			
			init_buf = (uint8 *)FATFS_BUFFER_ADDR;
			
			if(((init_buf[0]==0xE9)||(init_buf[0]==0xEB))&&
				(init_buf[510]==0x55)&&(init_buf[511]==0xAA)){
				blk_start_addr = 0;
			}
			else if((init_buf[510]==0x55)&&(init_buf[511]==0xAA)){
				blk_start_addr = init_buf[454];
				blk_start_addr |= init_buf[455]<<8;
				blk_start_addr |= init_buf[456]<<16;
				blk_start_addr |= init_buf[457]<<24;
			}
			DEBUGMSG(("blk_start_addr=0x%x\r\n",blk_start_addr));
			return RES_OK;
		}
		return STA_NOINIT;
		
		
	case USB :
		//result = USB_disk_initialize();
		// translate the reslut code here

		return stat;
	}
	return STA_NOINIT;
}



/*-----------------------------------------------------------------------*/
/* Return Disk Status                                                    */
/*-----------------------------------------------------------------------*/

DSTATUS disk_status (
	BYTE drv		/* Physical drive nmuber (0..) */
)
{
	DSTATUS stat=RES_OK;
	

	switch (drv) {
	case ATA :
		//result = ATA_disk_status();
		// translate the reslut code here

		return stat;

	case MMC :
		//result = MMC_disk_status();
		// translate the reslut code here

		return stat;

	case USB :
		//result = USB_disk_status();
		// translate the reslut code here

		return stat;
	}
	return STA_NOINIT;
}



/*-----------------------------------------------------------------------*/
/* Read Sector(s)                                                        */
/*-----------------------------------------------------------------------*/

DRESULT disk_read (
	BYTE drv,		/* Physical drive nmuber (0..) */
	BYTE *buff,		/* Data buffer to store read data */
	DWORD sector,	/* Sector address (LBA) */
	BYTE count		/* Number of sectors to read (1..255) */
)
{
	DRESULT res;
	INT8U err;
    
	
	switch (drv) {
	case ATA :
		 res = RES_ERROR;
		 break;
	case MMC :
		#if 0
        CLIOutputString("read:0x%x 0x%x\r\n",count,buff);
        err = CopyMovitoMem(HSMMC_CHANNEL, sector+blk_start_addr,count+1, (uint *)FATFS_BUFFER_ADDR, MOVI_INIT_REQUIRED);
		if(err>0){
            buf1 = (uint8 *)FATFS_BUFFER_ADDR;
			for(loop=0;loop<(count<<9);loop++){
                *buff++ = *buf1++;    
            }
    	}
	    #endif
		
      //  CLIOutputString("err:0x%x\r\n",err);
        
		if(count>1)
			err = SD_ReadMultiBlock(&hsmmc_card_0,sector+blk_start_addr,count,buff);
		else
			err = SD_ReadBlock(&hsmmc_card_0,sector+blk_start_addr,buff);
        
		if(err>0)
			return RES_ERROR;
		else
			return RES_OK;
		
	case USB :
		 res = RES_ERROR;
		 break;
	}
	return res;
}



/*-----------------------------------------------------------------------*/
/* Write Sector(s)                                                       */
/*-----------------------------------------------------------------------*/
/* The FatFs module will issue multiple sector transfer request
/  (count > 1) to the disk I/O layer. The disk function should process
/  the multiple sector transfer properly Do. not translate it into
/  multiple single sector transfers to the media, or the data read/write
/  performance may be drasticaly decreased. */

#if _READONLY == 0
DRESULT disk_write (
	BYTE drv,			/* Physical drive nmuber (0..) */
	const BYTE *buff,	/* Data to be written */
	DWORD sector,		/* Sector address (LBA) */
	BYTE count			/* Number of sectors to write (1..255) */
)
{
	DRESULT res;
	INT8U err;
    
	switch (drv) {
	case ATA :
        res = RES_ERROR;
        break;
	case MMC :
		return RES_OK;
		
	case USB :
        res = RES_ERROR;
        break;
	}
	return res;
}
#endif /* _READONLY */



/*-----------------------------------------------------------------------*/
/* Miscellaneous Functions                                               */
/*-----------------------------------------------------------------------*/

DRESULT disk_ioctl (
	BYTE drv,		/* Physical drive nmuber (0..) */
	BYTE ctrl,		/* Control code */
	void *buff		/* Buffer to send/receive control data */
)
{
	DRESULT res = RES_OK;
	//int result;

	switch (drv) {
	case ATA :
		// pre-process here

		//result = ATA_disk_ioctl(ctrl, buff);
		// post-process here

		return res;

	case MMC :
		// pre-process here

		//result = MMC_disk_ioctl(ctrl, buff);
		// post-process here

		return res;

	case USB :
		// pre-process here

		//result = USB_disk_ioctl(ctrl, buff);
		// post-process here

		return res;
	}
	return RES_PARERR;
}

DWORD get_fattime (void)
{
	return RES_OK;
}


